Accessibility Manual Testing Checklist
**Purpose:** Covers 60-70% of accessibility issues not caught by automated tools like axe-core.
**When to use:**
- Before major releases
- For UI changes in pull requests
- Quarterly accessibility audits
- When adding new components or features
**Automated vs Manual Testing:**
- **Automated (40%):** @axe-core/playwright, jest-axe - detects ARIA issues, missing labels, role problems
- **Manual (60%):** This checklist - keyboard navigation, screen readers, semantic HTML, mobile, edge cases
---
1. Keyboard Navigation
Automated tools cannot verify if keyboard navigation actually works or makes sense. Only manual testing can confirm:
1.1 Tab Order
- [ ] **Tab moves focus in logical order** (left-to-right, top-to-bottom)
- Test: Press Tab repeatedly through the page
- Expected: Focus follows visual reading order (not source code order)
- Common issues: Skip links appear, focus jumps to hidden elements
- [ ] **All interactive elements receive focus**
- Test: Tab through all buttons, links, inputs, dropdowns
- Expected: Every interactive element shows a visible focus indicator
- Common issues: Custom widgets don't accept focus, tabindex misuse
- [ ] **Focus indicator is visible** (2px solid, 3:1 contrast)
- Test: Tab to any element and look for the focus ring
- Expected: Clear outline or background change (WCAG 2.4.7: Focus Visible)
- Common issues:
outline: nonewithout replacement, low contrast focus
- [ ] **Tab skips hidden/disabled elements**
- Test: Verify hidden content and disabled form fields are skipped
- Expected: Tab moves to next visible/interactive element
- Common issues:
tabindex="0"on hidden elements traps focus
1.2 Keyboard Activation
- [ ] **Enter activates buttons and links**
- Test: Focus button/link, press Enter
- Expected: Same action as click/tap
- Common issues: Custom handlers only respond to mouse events
- [ ] **Space activates buttons and checkboxes**
- Test: Focus button/checkbox, press Space
- Expected: Buttons click, checkboxes toggle (WCAG 2.1.1: Keyboard)
- Common issues: Space key not handled in custom components
- [ ] **Arrow keys navigate dropdowns and menus**
- Test: Open a custom dropdown, use arrow keys
- Expected: Focus moves through options, up/down arrows work
- Common issues: Arrow keys ignored, focus doesn't move
- [ ] **Escape closes modals and cancels actions**
- Test: Open a modal/dialog, press Escape
- Expected: Modal closes, focus returns to trigger element
- Common issues: Escape doesn't work, focus trapped incorrectly
1.3 Focus Trapping
- [ ] **Modals trap focus** (Tab cycles within modal)
- Test: Open modal, press Tab repeatedly
- Expected: Focus cycles through modal content, doesn't reach page behind
- Common issues: Focus escapes behind modal, can't close with keyboard
- [ ] **Focus returns to triggering element after modal closes**
- Test: Open modal, close it (Escape or button)
- Expected: Focus is on the button that opened the modal
- Common issues: Focus lost, returns to top of page
- [ ] **Drawers/sidebars trap focus when open**
- Test: Open sidebar, press Tab
- Expected: Focus cycles within sidebar, doesn't reach main content
- Common issues: Focus escapes, can't access sidebar content
1.4 Skip Links
- [ ] **Skip navigation link visible on focus**
- Test: Tab from very top of page (before any content)
- Expected: "Skip to main content" link appears on first Tab
- Common issues: Skip link hidden off-screen, never receives focus
- [ ] **Skip link jumps to main content**
- Test: Activate skip link (press Enter)
- Expected: Focus moves to
<main>orid="main" - Common issues: Link goes to wrong element, focus not set
- [ ] **Multiple skip links for nav/main/footer**
- Test: Tab through page, look for multiple skip options
- Expected: Skip links for navigation, main content, footer
- Common issues: Only one skip link, doesn't help with complex layouts
---
2. Screen Reader Compatibility
Screen readers reveal the accessibility tree that automated tools scan. Only human testing confirms it's usable.
2.1 NVDA (Windows) - Free
- [ ] **Page title announced on load**
- Test: Open page, listen to announcement
- Expected: NVDA says title like "ATUM SaaS - Agent Dashboard"
- Common issues: Generic titles like "Page" or "Home"
- [ ] **Landmarks announced** (banner, nav, main, footer)
- Test: Press NVDA + D (landmarks list)
- Expected: Navigation landmarks appear (banner, navigation, main, contentinfo)
- Common issues: No landmarks, all content in one region
- [ ] **Headings hierarchy (h1 > h2 > h3) is logical**
- Test: Press H (next heading), Shift+H (previous heading)
- Expected: Single h1, heading levels not skipped
- Common issues: Multiple h1, h1 followed by h4, no headings
- [ ] **Form labels announced with input fields**
- Test: Navigate to form field with arrows
- Expected: NVDA says "Email, edit" or "Password, edit, required"
- Common issues: Unlabeled inputs read as "edit blank", placeholders as labels
- [ ] **Error messages announced after validation**
- Test: Submit invalid form, listen for feedback
- Expected: "Invalid email" or error message read immediately
- Common issues: Errors not announced, only shown visually (red text)
- [ ] **Dynamic content updates are announced** (aria-live)
- Test: Trigger page update (load more, filter change)
- Expected: NVDA announces "Loading more items" or "5 results found"
- Common issues: Silent updates, user doesn't know content changed
2.2 VoiceOver (macOS) - Built-in
- [ ] **Navigate by headings** (VO + H)
- Test: Press VO + H to jump between headings
- Expected: Move through h1, h2, h3 in order
- Common issues: Headings not announced, jumps randomly
- [ ] **Navigate by landmarks** (VO + U)
- Test: Press VO + U, select landmark from rotor
- Expected: List of landmarks appears (banner, nav, main, footer)
- Common issues: Landmarks missing, rotor shows nothing
- [ ] **Form controls announced correctly**
- Test: Navigate to form field (VO + arrow keys)
- Expected: "Email, edit text" or "Subscribe, checkbox, unchecked"
- Common issues: Role not announced (just "button"), state unclear
- [ ] **Focus announcements are accurate**
- Test: Tab through page, listen to focus changes
- Expected: Every focus change is announced with element name/role
- Common issues: Silent focus, "unknown" announced
2.3 Screen Reader Testing Tips
**Don't test everything:**
- Focus on user flows (login, agent creation, billing)
- Test complex components (modals, dropdowns, data tables)
- Verify dynamic content (search results, filtered lists)
**Use shortcuts:**
- NVDA: H (heading), F (form field), L (list), B (button)
- VoiceOver: VO + U (landmarks), VO + H (headings), VO + I (items)
---
3. Semantic HTML
Automated tools check for semantic tags, but only humans verify the tags make semantic sense.
3.1 Landmarks
- [ ] **
<header>for site header** - Test: View source, search for
<header> - Expected: Top navigation/banner in
<header>with role="banner" - Common issues:
<div class="header">instead of semantic tag
- [ ] **
<nav>for navigation** - Test: View source, find navigation areas
- Expected: Main nav, footer nav in
<nav>with role="navigation" - Common issues: Navigation in
<div>, no landmarks announced
- [ ] **
<main>for main content** - Test: View source, search for
<main> - Expected: Page content in
<main>with role="main" - Common issues: Content in
<div id="main">, no main landmark
- [ ] **
<footer>for footer** - Test: View source, find footer area
- Expected: Site footer in
<footer>with role="contentinfo" - Common issues: Footer in
<div class="footer">
- [ ] **
<aside>for sidebar content** - Test: View source, find sidebars/panels
- Expected: Related content in
<aside>with role="complementary" - Common issues: Sidebars in
<div>, not semantically related
3.2 Headings
- [ ] **Single h1 per page**
- Test: View source, count
<h1>tags - Expected: Exactly one
<h1>per page - Common issues: Multiple h1 for logo/title/content
- [ ] **Heading levels not skipped**
- Test: View source, check heading sequence
- Expected: h1 → h2 → h3 (no h1 → h4 jumps)
- Common issues: h1 followed by h3 or h4 for styling
- [ ] **Headings describe content sections**
- Test: Read headings out of context
- Expected: Headings make sense without page content
- Common issues: Generic headings like "Section 1" or "Info"
3.3 Lists
- [ ] **Related items use
<ul>or<ol>** - Test: View source, find groups of related items
- Expected: Navigation menus, bullet points in list markup
- Common issues: Lists made of
<div>elements
- [ ] **Navigation menus use list markup**
- Test: Inspect nav menu, view source
- Expected:
<nav><ul><li><a>...structure - Common issues: Navigation links in
<span>or<div>
3.4 Forms
- [ ] **All inputs have associated labels**
- Test: Click label text, does input get focus?
- Expected: Clicking label focuses the input (implicit/explicit association)
- Common issues: Labels not connected via
forattribute or nesting
- [ ] **Required fields indicated with
aria-required** - Test: Inspect required input, check attributes
- Expected:
aria-required="true"orrequiredattribute - Common issues: Required only shown visually (asterisk, red border)
- [ ] **Error messages linked with
aria-describedby** - Test: Trigger error, inspect input and error message
- Expected:
aria-describedby="error-id"connects input to error - Common issues: Errors not linked to inputs programmatically
- [ ] **Field validation announced**
- Test: Submit invalid form with screen reader
- Expected: "3 errors, first error in Email field"
- Common issues: Errors shown visually but not announced
---
4. Mobile Accessibility
Automated tools can't test touch interactions or mobile behavior.
4.1 Touch Targets
- [ ] **Interactive elements ≥ 44x44 CSS pixels**
- Test: Open DevTools, measure button/link dimensions
- Expected: Width and height both ≥ 44px (WCAG 2.5.5: Target Size)
- Common issues: Small buttons (< 40px), inline links too close
- [ ] **Touch targets have spacing between them**
- Test: Tap adjacent buttons, do they activate separately?
- Expected: 8px+ spacing between targets (iOS/android guideline)
- Common issues: Buttons touching, mis-taps common
- [ ] **No mouse-only interactions** (hover menus)
- Test: Try to navigate without hover (finger/touch)
- Expected: All content accessible without hover
- Common issues: Dropdowns only open on hover, no tap alternative
4.2 Orientation
- [ ] **Content usable in portrait and landscape**
- Test: Rotate device or resize browser to mobile width
- Expected: No horizontal scroll, content adapts to orientation
- Common issues: Landscape mode breaks, horizontal scroll required
- [ ] **No orientation lock required**
- Test: Rotate device, does content reflow?
- Expected: Works in both portrait and landscape
- Common issues: "Rotate your device" message, forces one orientation
4.3 Zoom
- [ ] **Content zooms to 200% without horizontal scroll**
- Test: Browser zoom to 200% (Cmd/Ctrl +)
- Expected: No horizontal scroll, text reflows (WCAG 1.4.10: Reflow)
- Common issues: Fixed-width containers, horizontal scroll at 200%
- [ ] **Text reflows when zoomed**
- Test: Browser zoom to 200%, check layout
- Expected: Text wraps, columns stack, no content cut off
- Common issues: Two-column layout breaks at 200% zoom
- [ ] **No pinch-zoom required** (viewport meta tag)
- Test: Check viewport meta tag in source
- Expected:
<meta name="viewport" content="width=device-width, initial-scale=1"> - Common issues:
user-scalable=noprevents zoom (WCAG violation)
4.4 Responsive
- [ ] **Layout adapts to different screen sizes**
- Test: Resize browser from desktop to mobile width
- Expected: Layout transitions smoothly, no content overlap
- Common issues: Breakpoints break, content overlaps at certain widths
- [ ] **Touch targets remain accessible on mobile**
- Test: Check button/link sizes on mobile viewport
- Expected: All interactive elements ≥ 44x44px
- Common issues: Desktop-sized buttons, links too small on mobile
---
5. Edge Cases (Not Caught by Automated Tools)
Automated tools scan the DOM, but they can't verify behavior over time or complex interactions.
5.1 Dynamic Content
- [ ] **Page changes announced with aria-live regions**
- Test: Trigger dynamic update (search, filter, async load)
- Expected: Screen reader announces change ("5 results found")
- Common issues: Silent updates, user doesn't know page changed
- [ ] **Loading states are announced**
- Test: Submit form that loads data
- Expected: "Loading..." or spinner announced (not visible)
- Common issues: Loading only visible (spinner), not announced
- [ ] **Modal open/close announced**
- Test: Open modal with screen reader
- Expected: "Dialog opened" or role="dialog" announced
- Common issues: Modal opens silently, screen reader still reading background
5.2 Custom Components
- [ ] **Custom dropdowns have proper ARIA roles**
- Test: Inspect custom dropdown element
- Expected:
role="combobox",aria-expanded,aria-haspopup - Common issues: Custom widget looks like dropdown but acts like div
- [ ] **Custom checkboxes implement aria-checked**
- Test: Inspect custom checkbox/toggle
- Expected:
role="checkbox",aria-checked="true/false" - Common issues: Visual toggle not exposed as checkbox to screen readers
- [ ] **Custom sliders implement aria-valuenow/min/max**
- Test: Inspect custom range slider
- Expected:
role="slider",aria-valuenow,aria-valuemin,aria-valuemax - Common issues: Slider value not exposed, "unknown" announced
5.3 Drag and Drop
- [ ] **Keyboard alternative provided**
- Test: Try to reorder items without mouse
- Expected: Arrow keys or alternative method to reorder
- Common issues: Drag-and-drop only, no keyboard option
- [ ] **Instructions are visible/announced**
- Test: Check if drag-and-drop instructions are readable
- Expected: "Drag to reorder" or similar instructions visible/announced
- Common issues: Drag-and-drop area has no instructions
5.4 Time-Based Media
- [ ] **Auto-playing content can be paused**
- Test: Find auto-playing video/carousel
- Expected: Pause/stop button available and accessible
- Common issues: Auto-play with no pause control (WCAG 2.2.2: Pause, Stop, Hide)
- [ ] **Moving content has pause/stop controls**
- Test: Find auto-scrolling content or animation
- Expected: Pause button available, motion stops
- Common issues: Carousels auto-advance without pause
---
6. Images and Media
Automated tools detect missing alt text, but not whether it's meaningful.
6.1 Alt Text
- [ ] **Informative images have descriptive alt**
- Test: Inspect informative image (icon, photo, diagram)
- Expected:
alt="User profile picture"oralt="Sales trend chart" - Common issues: Generic alt like "image" or "photo"
- [ ] **Decorative images have alt=""**
- Test: Find decorative images (spacing, styling)
- Expected:
alt=""orrole="presentation" - Common issues: Decorative images announced as "image" or filename
- [ ] **Complex images have long descriptions**
- Test: Find charts, graphs, complex diagrams
- Expected: Long description via
aria-describedby, longdesc, or adjacent text - Common issues: Complex image with brief/missing alt
6.2 Captions
- [ ] **Videos have synchronized captions**
- Test: Play video, check for caption track
- Expected:
<track kind="captions">or captions available - Common issues: No captions, auto-generated captions only
- [ ] **Audio-only content has transcripts**
- Test: Find audio-only content (podcast, voice note)
- Expected: Transcript text available on page
- Common issues: Audio without text alternative
---
7. Error Handling
Automated tools can't verify if error recovery is actually possible.
- [ ] **Errors announced with aria-live**
- Test: Trigger error, check if screen reader announces it
- Expected: Error message announced immediately (aria-live="assertive")
- Common issues: Errors shown but not announced
- [ ] **Error messages linked to inputs**
- Test: Click error text, does input get focus?
- Expected: Clicking error focuses related input
- Common issues: Errors not linked, unclear which field has error
- [ ] **Recovery suggestions provided**
- Test: Trigger error, read error message
- Expected: "Invalid email format" or "Password must be 8+ characters"
- Common issues: "Invalid input" with no guidance
- [ ] **Form validation doesn't submit with errors**
- Test: Submit invalid form
- Expected: Form blocks submission, errors shown
- Common issues: Invalid data submits, backend errors
---
PR Review Integration
For UI changes in pull requests, reviewers should verify:
**Quick checks (2 minutes):**
- **Keyboard navigation**: Tab through, focus indicator visible?
- **Focus indicators**: Can you see where you are?
- **Screen reader**: Navigate with VO/NVDA, does it make sense?
- **Touch targets**: If mobile component, are buttons ≥ 44x44px?
**Full checks (10 minutes):**
- Run through relevant sections of this checklist
- Test complex components (modals, dropdowns, forms)
- Verify dynamic content updates are announced
- Check responsive behavior on mobile viewport
**When to skip:**
- Non-UI changes (backend, infrastructure, documentation)
- Bug fixes that don't change component structure
- Minor styling tweaks (unless affecting focus/contrast)
---
Testing Tools
**Screen Readers:**
- NVDA (Windows, free): https://www.nvaccess.org/
- VoiceOver (macOS, built-in): Cmd + F5 to enable
- JAWS (Windows, paid): https://www.freedomscientific.com/
**Keyboard Testing:**
- Unplug mouse/disable trackpad
- Use Tab, Enter, Space, Escape, Arrow keys
**Mobile Testing:**
- Chrome DevTools device emulation (Cmd + Shift + M)
- Real device testing (iPhone, Android)
**Contrast Checking:**
npm run check:contrast "#FFFFFF" "#000000"**Automated Scanning:**
npm run test:a11y # Run axe-core E2E tests
npm run test:a11y:unit # Run jest-axe component tests---
References
- **WCAG 2.1 Guidelines:** https://www.w3.org/WAI/WCAG21/quickref/
- **ARIA Authoring Practices:** https://www.w3.org/WAI/ARIA/apg/
- **WebAIM Checklist:** https://webaim.org/standards/wcag/checklist
- **Accessibility Insights:** https://accessibilityinsights.io/
---
**Last Updated:** 2026-03-22
**Maintained by:** ATOM SaaS Team
**Questions:** Contact the accessibility working group